package com.gcxy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gcxy.constant.StringConst;
import com.gcxy.core.PageVO;
import com.gcxy.core.R;
import com.gcxy.dto.teacher.AddTeacherInfoDTO;
import com.gcxy.dto.teacher.TeacherPageDTO;
import com.gcxy.dto.teacher.UpdateTeacherDTO;
import com.gcxy.dto.teacher.UploadSignDTO;
import com.gcxy.entity.*;
import com.gcxy.enums.ResultCodeEnum;
import com.gcxy.mapper.UserMapper;
import com.gcxy.service.*;
import com.gcxy.utils.BeanCopyUtil;
import com.gcxy.utils.UserUtil;
import com.gcxy.vo.role.RoleVO;
import com.gcxy.vo.teacher.TeacherAllListVO;
import com.gcxy.vo.teacher.TeacherPageVO;

import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

import static com.gcxy.constant.StringConst.DEFAULT_SIGN_FILE_PATH;
import static com.gcxy.constant.StringConst.MAX_UPLOAD_FILE_SIZE;

/**
 * Copyright (C), 2024-2024, BUG闭退！
 * Author: Huang先森
 * Date: 2024/8/2 10:23
 * FileName: TeacherServiceImpl
 * Description:
 */
@Service
public class TeacherServiceImpl extends ServiceImpl<UserMapper, User> implements TeacherService {

    @Resource
    private StudentTeacherService studentTeacherService;

    @Resource
    private UserRoleService userRoleService;

    @Resource
    private UserService userService;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private AgencyService agencyService;

    @Resource
    private UserMapper userMapper;

    @Resource
    private SemesterService semesterService;


    /**
     * 获取本学期内当前组织下的名誉教师信息
     *
     * @param semesterId
     * @param agencyId
     * @return
     */
    @Override
    public List<User> getHonoraryTeacher(Integer semesterId, Integer agencyId) {
        return getHonoraryTeacher(semesterId, agencyId, null);
    }

    /**
     * 根据教师名称获取本学期内当前组织下的名誉教师信息
     *
     * @param semesterId
     * @param agencyId
     * @param honoraryTeacherName
     * @return
     */
    @Override
    public List<User> getHonoraryTeacher(Integer semesterId, Integer agencyId, String honoraryTeacherName) {
        List<StudentTeacher> allStudentTeacher = studentTeacherService.getTeacherBySemesterId(semesterId);
        if (CollectionUtils.isEmpty(allStudentTeacher)) {
            return new ArrayList<>();
        }
        List<Integer> honoraryTeacher = allStudentTeacher.stream().map(StudentTeacher::getHonoraryTeacherId).distinct().collect(Collectors.toList());
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getAgencyId, agencyId)
                .like(StringUtils.isNotBlank(honoraryTeacherName), User::getFullName, honoraryTeacherName)
                .in(User::getId, honoraryTeacher);
        return list(queryWrapper);
    }

    /**
     * 上传老师签名
     *
     * @param uploadSignDTO
     * @return
     */
    @Override
    public R<?> uploadTeacherSign(UploadSignDTO uploadSignDTO) {
        String userAccount = uploadSignDTO.getTeacherAccount();
        String file = uploadSignDTO.getTeacherSign();
        if (file.isEmpty() || StringUtils.isEmpty(file)) {
            if (userAccount.isEmpty()) {
                userAccount = userService.getUserInfo().getUsername();
            }
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getUsername, userAccount);
            User user = getOne(queryWrapper);
            if (ObjectUtils.isEmpty(user)) {
                return R.Failed(ResultCodeEnum.BUSINESS_ERROR.getCode(), "用户不存在！");
            }
            if (!user.getSignature().isEmpty()) {
                return R.Success("上传成功！");
            }
            userService.update(getOne(queryWrapper), new UpdateWrapper<User>().set("signature", null));
            return R.Success("修改成功");
        }
        if (userAccount == null || userAccount.isEmpty()) {
            userAccount = userService.getUserInfo().getUsername();
        }
        File oldFile = new File(uploadSignDTO.getTeacherSign());
        String fileExtension = uploadSignDTO.getTeacherSign().substring(uploadSignDTO.getTeacherSign().lastIndexOf("."));
        String uniqueFilename = userAccount + fileExtension;
        String targetFilePath = DEFAULT_SIGN_FILE_PATH + uniqueFilename;
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, userAccount);
        User user = userService.getOne(queryWrapper);
        // 删除原来的文件
        File oldFile_ = new File(targetFilePath);
        if (oldFile_.exists()) {
            oldFile_.delete();
        }
        // 创建一个新的File对象，表示重命名后的文件
        File newFile = new File(targetFilePath);
        if (!oldFile.renameTo(newFile)) {
            File file_ = new File(uploadSignDTO.getTeacherSign());
            if (file_.exists()) {
                file_.delete();
            }
            return R.Failed("上传签名失败，");
        }

        if (ObjectUtils.isEmpty(user)) {
            return R.Failed(ResultCodeEnum.BUSINESS_ERROR.getCode(), "用户不存在！");
        }
        user.setSignature(targetFilePath);
        boolean updateUser = userService.updateById(user);
        if (!updateUser) {
            return R.Failed(ResultCodeEnum.BUSINESS_ERROR.getCode(), "上传失败！");
        }

        return R.Success("上传成功！");
    }

    /**
     * 获取用户签名路径
     *
     * @param
     * @return
     */
    @Override
    public R<?> getSign() {
        User user = userService.getById(UserUtil.getCurrentUser().getId());
        if (ObjectUtils.isEmpty(user.getSignature()) || user.getSignature().isEmpty()){
            return R.Success("");
        }
        return R.Success(userService.getById(UserUtil.getCurrentUser().getId()).getSignature());
    }

    @Override
    public R<?> uploadSignature(MultipartFile file) {
        if (file == null || file.isEmpty() || com.baomidou.mybatisplus.core.toolkit.ObjectUtils.isEmpty(file.getOriginalFilename())) {
            return R.Failed(ResultCodeEnum.BUSINESS_ERROR.getCode(), "文件不能为空！");
        }
        if (file.getSize() > MAX_UPLOAD_FILE_SIZE) {
            return R.Failed(ResultCodeEnum.BUSINESS_ERROR.getCode(), "文件大小不能超过5M！");
        }
        String originalFilename = file.getOriginalFilename();
        if (!(originalFilename.endsWith(".png") || originalFilename.endsWith(".jpg"))) {
            return R.Failed(ResultCodeEnum.BUSINESS_ERROR.getCode(), "文件类型错误，只支持：png、jpg！");
        }
        //如果目录不存在，则生成对应目录
        File defaultSignFile = new File(DEFAULT_SIGN_FILE_PATH);
        if (!defaultSignFile.exists()) {
            boolean mkdirs = defaultSignFile.mkdirs();
            if (!mkdirs) {
                return R.Failed("上传失败！");
            }
        }

        try {
            String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
            String uniqueFilename = UUID.randomUUID().toString() + fileExtension;
            String targetFilePath = DEFAULT_SIGN_FILE_PATH + uniqueFilename;

            //目标文件
            File targetFile = new File(targetFilePath);
            //传输文件到指定目录
            file.transferTo(targetFile);
            return R.Success(targetFilePath);
        } catch (Exception e) {
            log.error("文件上传失败", e);
            return R.Failed("文件上传失败");
        }
    }

    @Override
    public R<?> deleteSignature() {
        // 获取文件夹下所有文件名

//        List<User> list = list();
//        for (User user : list) {
//            if (!user.getSignature().isEmpty()) {
//                File oldFile = new File(user.getSignature());
//                if (oldFile.exists()) {
//                    oldFile.delete();
//                }
//            }
//        }
        return R.Success("删除成功！");
    }


    /**
     * 获取当前组织所有教师姓名
     *
     * @return
     */
    @Override
    public R<List<TeacherAllListVO>> getAllTeacherName(Integer agencyId) {
        List<Integer> userList = userRoleService.getAllUserByRoleId(StringConst.TEACHER);
        if (CollectionUtils.isEmpty(userList)) {
            return R.Success(new ArrayList<>());
        }
//        // 超级管理员查询全部老师，其他查询当前组织下所有老师
//        boolean isSuperAdmin = userService.isInvalidUserResourcePermission(PermissionConst.SELECT_INSERT_OTHER_AGENCY_TEACHER_DATA);
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
//
//        if (ObjectUtils.isEmpty(userService.getUserInfo().getAgency())) {
//            if (!isSuperAdmin) {
//                return R.Failed("当前用户无法查询组织内老师");
//            }
//            queryWrapper.in(User::getId, userList);
//        } else {
//            queryWrapper.in(User::getId, userList).eq(User::getAgencyId, userService.getUserInfo().getAgency().getId());
//        }
        queryWrapper.in(User::getId, userList).eq(User::getAgencyId, agencyId);
        List<User> users = list(queryWrapper);
        List<TeacherAllListVO> teacherAllListVOS = users.stream()
                .filter(Objects::nonNull)
                .map(user -> BeanCopyUtil.copy(user, TeacherAllListVO.class))
                .collect(Collectors.toList());
        return R.Success(teacherAllListVOS);

    }

    /**
     * 新增老师
     *
     * @param addTeacherInfoDTO
     * @return
     */
    @Transactional
    @Override
    public R<?> insertTeacher(AddTeacherInfoDTO addTeacherInfoDTO) {
        if (addTeacherInfoDTO.getAgencyId() == null) {
            return R.Failed("组织id不能为空");
        }
        //查询用户账号和名称是否已经存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>()
                .eq(User::getUsername, addTeacherInfoDTO.getTeacherAccount());
        User selectUser = getOne(queryWrapper);

        if (!ObjectUtils.isEmpty(selectUser)) {
            LambdaQueryWrapper<StudentTeacher> queryWrapper1 = new LambdaQueryWrapper<>();
            // 根据学生教师表中PracticalTeacherId、HonoraryTeacherId、semesterId 判断是否有绑定学生
            queryWrapper1.eq(StudentTeacher::getSemesterId, semesterService.getCurrentSemester().getId())
                    .eq(StudentTeacher::getPracticalTeacherId, selectUser.getId())
                    .or()
                    .eq(StudentTeacher::getHonoraryTeacherId, selectUser.getId());
            List<StudentTeacher> studentTeachers = studentTeacherService.list(queryWrapper1);
            Agency agency = agencyService.getById(selectUser.getAgencyId());

            if (selectUser.getAgencyId() != null && CollectionUtils.isNotEmpty(studentTeachers)) {
                return R.Failed(String.format("账号在%s中已绑定学生!", agency.getName()));
            }

            selectUser.setAgencyId(addTeacherInfoDTO.getAgencyId());
            selectUser.setUsername(addTeacherInfoDTO.getTeacherAccount());
            selectUser.setFullName(addTeacherInfoDTO.getTeacherName());

            // 上传签名
            if (!StringUtils.isEmpty(addTeacherInfoDTO.getTeacherSign())) {
                File oldFile = new File(addTeacherInfoDTO.getTeacherSign());
                String fileExtension = addTeacherInfoDTO.getTeacherSign().substring(addTeacherInfoDTO.getTeacherSign().lastIndexOf("."));
                String uniqueFilename = addTeacherInfoDTO.getTeacherAccount() + fileExtension;
                String targetFilePath = DEFAULT_SIGN_FILE_PATH + uniqueFilename;

                // 先删除原来的文件
                File oldFile_ = new File(targetFilePath);
                if (oldFile_.exists()) {
                    oldFile_.delete();
                }

                // 创建一个新的File对象，表示重命名后的文件
                File newFile = new File(targetFilePath);
                if (!oldFile.renameTo(newFile)) {
                    File file = new File(addTeacherInfoDTO.getTeacherSign());
                    if (file.exists()) {
                        file.delete();
                    }
                    return R.Failed("上传签名失败，");
                }
                selectUser.setSignature(targetFilePath);
            }

            boolean update = updateById(selectUser);

            if (!update) {
                return R.Failed("新增老师失败:更新用户信息异常！");
            }
            // 获取当前用户是否有某个角色
            List<RoleVO> roleVOList = userRoleService.getRoleByUserId(selectUser.getId());
            if (CollectionUtils.isEmpty(roleVOList) | !roleVOList.stream().anyMatch(roleVO -> roleVO.getId().equals(StringConst.TEACHER))) {
                // 设置用户角色
                boolean saveRole = userRoleService.insertUserRole(selectUser.getId(), StringConst.TEACHER);
                if (!saveRole) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return R.Failed("新增教师授权失败！重新添加");
                }
            }
            return R.Success("新增老师成功！");
        }

        User user = new User();
        user.setUsername(addTeacherInfoDTO.getTeacherAccount());
        user.setFullName(addTeacherInfoDTO.getTeacherName());
        user.setAgencyId(addTeacherInfoDTO.getAgencyId());
        user.setEnabled(true);
        user.setPassword(passwordEncoder.encode(StringConst.DEFAULT_PASSWORD));
        // 上传签名
        if (!StringUtils.isEmpty(addTeacherInfoDTO.getTeacherSign())) {
            File oldFile = new File(addTeacherInfoDTO.getTeacherSign());
            String fileExtension = addTeacherInfoDTO.getTeacherSign().substring(addTeacherInfoDTO.getTeacherSign().lastIndexOf("."));
            String uniqueFilename = addTeacherInfoDTO.getTeacherAccount() + fileExtension;
            String targetFilePath = DEFAULT_SIGN_FILE_PATH + uniqueFilename;
            // 创建一个新的File对象，表示重命名后的文件
            File newFile = new File(targetFilePath);
            if (!oldFile.renameTo(newFile)) {
                File file = new File(addTeacherInfoDTO.getTeacherSign());
                if (file.exists()) {
                    file.delete();
                }
                return R.Failed("上传签名失败，");
            }
            user.setSignature(targetFilePath);
        }
        boolean result = save(user);
        if (!result) {
            return R.Failed("新增老师失败");
        }
        // 设置用户角色
        boolean saveRole = userRoleService.insertUserRole(user.getId(), StringConst.TEACHER);
        if (!saveRole) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return R.Failed("新增教师授权失败！重新添加");
        }
        return R.Success();
    }

    /**
     * 更新老师
     *
     * @param updateTeacherDTO
     * @return
     */
    @Override
    public R<?> updateTeacher(UpdateTeacherDTO updateTeacherDTO) {
        User user = getById(updateTeacherDTO.getId());
        if (ObjectUtils.isEmpty(user)) {
            return R.Failed("用户不存在，无法修改");
        }
        // 判断数据库中是否存在该username
        if (!user.getUsername().equals(updateTeacherDTO.getTeacherAccount())) {
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>()
                    .eq(User::getUsername, updateTeacherDTO.getTeacherAccount());
            User selectUser = getOne(queryWrapper);
            if (!ObjectUtils.isEmpty(selectUser)) {
                return R.Failed("用户账号已存在，请重新输入");
            }
        }

//        user.setId(updateTeacherDTO.getId());
        user.setUsername(updateTeacherDTO.getTeacherAccount());
        user.setFullName(updateTeacherDTO.getTeacherName());
        user.setEnabled(true);

        // 上传签名
        if (!StringUtils.isEmpty(updateTeacherDTO.getTeacherSign())) {
            File oldFile = new File(updateTeacherDTO.getTeacherSign());
            String fileExtension = updateTeacherDTO.getTeacherSign().substring(updateTeacherDTO.getTeacherSign().lastIndexOf("."));
            String uniqueFilename = updateTeacherDTO.getTeacherAccount() + fileExtension;
            String targetFilePath = DEFAULT_SIGN_FILE_PATH + uniqueFilename;
            // 先删除原来的文件
            File oldFile_ = new File(targetFilePath);
            if (oldFile_.exists()) {
                oldFile_.delete();
            }
            File newFile = new File(targetFilePath);
            if (!oldFile.renameTo(newFile)) {
                File file = new File(updateTeacherDTO.getTeacherSign());
                if (file.exists()) {
                    file.delete();
                }
                return R.Failed("上传签名失败，");
            }
            user.setSignature(targetFilePath);
        } else {
            // 删除图片
            if (!StringUtils.isEmpty(user.getSignature())) {
                File file = new File(user.getSignature());
                if (file.exists()) {
                    file.delete();
                }
                user.setSignature("");
            }
        }

        boolean update = updateById(user);
        if (!update) {
            return R.Failed("更新老师信息失败！");
        }
        return R.Success();
    }

    /**
     * 删除老师
     *
     * @param id
     * @return
     */
    @Override
    public R<?> deleteTeacher(Integer id) {
        if (id == null) {
            return R.Failed("id不能为空");
        }
        User user = getById(id);
        if (ObjectUtils.isEmpty(user)) {
            return R.Failed("删除的用户不存在！");
        }
        LambdaQueryWrapper<StudentTeacher> studentTeacherLambdaQueryWrapper = new LambdaQueryWrapper<StudentTeacher>()
                .eq(StudentTeacher::getHonoraryTeacherId, user.getId())
                .or()
                .eq(StudentTeacher::getPracticalTeacherId, user.getId());
        List<StudentTeacher> studentTeacherList = studentTeacherService.list(studentTeacherLambdaQueryWrapper);
        // 存在关联学生 不能删除
        if (CollectionUtils.isNotEmpty(studentTeacherList)) {
            return R.Failed("该教师存在关联学生，无法删除");
        }
        // TODO 删除角色关联组织数据
        LambdaUpdateWrapper<User> userLambdaUpdateWrapper = new LambdaUpdateWrapper<User>();
        userLambdaUpdateWrapper.eq(User::getId, user.getId())
                .set(User::getAgencyId, null);


        boolean result = update(userLambdaUpdateWrapper);
        if (!result) {
            return R.Failed("删除教师失败");
        }
        return R.Success("删除教师成功");
    }

    /**
     * 根据条件分页获取所有老师
     *
     * @param teacherPageDTO
     * @return
     */
    @Override
    public R<?> getTeacherPageByCondition(TeacherPageDTO teacherPageDTO) {
        // 判断该用户是否具有查询其他组织教师的权限
        if (teacherPageDTO.getAgencyId() == null) {
            return R.Failed("组织编号不能为空");
        }
        Page<TeacherPageVO> teacherPageData = userMapper.selectTeacherStudentPageByCondition(new Page<>(teacherPageDTO.getPageNo(), teacherPageDTO.getPageSize()), teacherPageDTO);
        PageVO pageVO = BeanCopyUtil.copy(teacherPageData, PageVO.class);
        return R.Success(pageVO);
    }
}
